package com.central.generator.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Objects;

/**
 * @author yuan
 */
@Slf4j
@RestController
@ControllerAdvice
public class ExceptionConfig {
    /**
     * 请求参数校验错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResultError validateException(MethodArgumentNotValidException e) {
        log.error("请求参数校验错误", e);
        return ResultError.error(ResultCode.VALIDATE.getCode(), Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage());
    }

    /**
     * 请求类型转换错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(HttpMessageConversionException.class)
    public ResultError parameterTypeException(HttpMessageConversionException e) {
        log.error("请求类型转换错误", e);
        return ResultError.error();
    }

    /**
     * 请求类型不支持错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResultError parameterTypeException(HttpRequestMethodNotSupportedException e) {
        log.error("请求类型不支持错误", e);
        return ResultError.error();
    }

    /**
     * 请求缺少必要参数错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResultError parameterTypeException(MissingServletRequestParameterException e) {
        log.error("请求缺少必要参数错误", e);
        return ResultError.error(ResultCode.VALIDATE.getCode(), ResultCode.VALIDATE.getDesc());
    }

    /**
     * 请求错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(BindException.class)
    public ResultError parameterTypeException(BindException e) {
        log.error("请求错误", e);
        return ResultError.error();
    }

    /**
     * 空指针错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(NullPointerException.class)
    public ResultError parameterTypeException(NullPointerException e) {
        log.error("空指针错误", e);
        return ResultError.error();
    }

    /**
     * 请求资源未找到错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResultError notFountException(NoHandlerFoundException e) {
        log.error("请求资源未找到错误", e);
        return ResultError.error(ResultCode.NOT_FOUND.getCode(), ResultCode.NOT_FOUND.getDesc());
    }

    /**
     * 文件资源未找到错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(FileNotFoundException.class)
    public ResultError notFountException(FileNotFoundException e) {
        log.error("文件资源未找到错误", e);
        return ResultError.error(ResultCode.NOT_FOUND.getCode(), ResultCode.NOT_FOUND.getDesc());
    }

    /**
     * IO错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(value = IOException.class)
    public ResultError ioException(IOException e) {
        log.error("IO错误", e);
        return ResultError.error();
    }

    /**
     * 运行时错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(value = RuntimeException.class)
    public ResultError runtimeException(RuntimeException e) {
        log.error("运行时错误", e);
        return ResultError.error();
    }

    /**
     * 其他错误
     *
     * @param e 错误
     * @return 错误信息
     */
    @ExceptionHandler(value = Exception.class)
    public ResultError exception(Exception e) {
        log.error("其他错误", e);
        return ResultError.error();
    }
}
